package com.codeplatform.controller;

import com.codeplatform.common.AppConstants;
import com.codeplatform.dto.CodeExecutionRequest;
import com.codeplatform.dto.CodeExecutionResult;
import com.codeplatform.entity.CodeRecord;
import com.codeplatform.entity.User;
import com.codeplatform.service.CodeExecutionService;
import com.codeplatform.service.CodeRecordService;
import com.codeplatform.util.SecurityValidator;
import com.codeplatform.util.JwtUtil;
import com.codeplatform.common.Result;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代码执行控制器
 */
@Api(tags = "代码执行管理")
@Slf4j
@RestController
@RequestMapping("/code")
@Validated
public class CodeExecutionController {
    
    @Autowired
    private CodeExecutionService codeExecutionService;
    
    @Autowired
    private CodeRecordService codeRecordService;
    
    @Autowired
    private SecurityValidator securityValidator;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    /**
     * 获取代码记录历史
     * @param page 页码
     * @param size 每页大小
     * @param language 编程语言过滤
     * @return 代码记录列表
     */
    @GetMapping("/records")
    public Result<Map<String, Object>> getCodeRecords(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = AppConstants.Pagination.DEFAULT_SIZE_STR) int size,
            @RequestParam(required = false) String language,
            HttpServletRequest request) {
        try {
            // 从请求中获取当前用户
            User currentUser = (User) request.getAttribute("currentUser");
            Long userId = currentUser != null ? currentUser.getId() : null;
            
            log.info("获取代码记录历史，用户ID: {}, 页码: {}, 大小: {}, 语言: {}", userId, page, size, language);
            
            // 如果用户未登录，返回空列表
            if (userId == null) {
                Map<String, Object> result = new HashMap<>();
                result.put("records", List.of());
                result.put("total", 0);
                result.put("page", page);
                result.put("size", size);
                return Result.success(result, "获取代码记录成功");
            }
            
            // 获取用户的代码记录
            List<CodeRecord> records = codeRecordService.getUserCodeRecords(userId, page, size, language);
            long total = codeRecordService.getUserCodeRecordCount(userId, language);
            
            Map<String, Object> result = new HashMap<>();
            result.put("records", records);
            result.put("total", total);
            result.put("page", page);
            result.put("size", size);
            
            return Result.success(result, "获取代码记录成功");
            
        } catch (Exception e) {
            log.error("获取代码记录失败", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }
    
    /**
     * 执行代码
     */
    @PostMapping("/execute")
    public Result<CodeExecutionResult> executeCode(@Valid @RequestBody CodeExecutionRequest request, HttpServletRequest httpRequest) {
        try {
            log.info("收到代码执行请求，语言: {}", request.getLanguage());
            
            // 尝试获取用户ID（如果用户已登录）
            try {
                Long userId = getUserIdFromRequest(httpRequest);
                if (userId != null) {
                    request.setUserId(userId);
                    log.debug("设置用户ID: {}", userId);
                }
            } catch (Exception e) {
                log.debug("获取用户ID失败，可能是匿名用户: {}", e.getMessage());
                // 匿名用户也可以执行代码，不影响执行
            }
            
            // 执行代码
            CodeExecutionResult result = codeExecutionService.executeCode(request);
            
            // 如果需要保存代码记录
            if (request.getUserId() != null && request.getTitle() != null) {
                try {
                    CodeRecord codeRecord = codeRecordService.saveCodeRecord(request, result);
                    
                    // 增加执行次数
                    codeRecordService.incrementExecutionCount(codeRecord.getId());
                    
                    // 将代码记录ID添加到结果中
                    result.setRecordId(codeRecord.getId());
                    
                    log.info("代码记录已保存，ID: {}", codeRecord.getId());
                } catch (Exception e) {
                    log.warn("保存代码记录失败", e);
                    // 不影响代码执行结果
                }
            }
            
            if (result.getSuccess()) {
                return Result.success(result, "代码执行成功");
            } else {
                return Result.error(result.getStatusMessage(), result);
            }
            
        } catch (Exception e) {
            log.error("代码执行异常", e);
            return Result.error("系统异常: " + e.getMessage());
        }
    }
    
    /**
     * 验证代码语法
     */
    @PostMapping("/validate")
    public Result<CodeExecutionResult> validateCode(@RequestBody Map<String, String> request) {
        try {
            String language = request.get("language");
            String code = request.get("code");
            
            if (language == null || code == null) {
                return Result.error("语言和代码不能为空");
            }
            
            log.info("收到语法验证请求，语言: {}", language);
            
            // 验证语法
            CodeExecutionResult result = codeExecutionService.validateSyntax(language, code);
            
            return Result.success(result, "语法验证完成");
            
        } catch (Exception e) {
            log.error("语法验证异常", e);
            return Result.error("验证异常: " + e.getMessage());
        }
    }
    
    /**
     * 获取支持的编程语言
     */
    @GetMapping("/languages")
    public Result<Map<String, Object>> getSupportedLanguages() {
        try {
            String[] languages = codeExecutionService.getSupportedLanguages();
            
            Map<String, Object> result = new HashMap<>();
            result.put("languages", languages);
            result.put("count", languages.length);
            
            // 添加语言详细信息
            Map<String, Map<String, String>> languageDetails = new HashMap<>();
            for (String lang : languages) {
                Map<String, String> details = new HashMap<>();
                details.put("name", getLanguageDisplayName(lang));
                details.put("extension", getLanguageExtension(lang));
                details.put("template", codeExecutionService.getTemplateCode(lang));
                languageDetails.put(lang, details);
            }
            result.put("details", languageDetails);
            
            return Result.success(result, "获取语言列表成功");
            
        } catch (Exception e) {
            log.error("获取语言列表异常", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取语言模板代码
     */
    @GetMapping("/template/{language}")
    public Result<String> getTemplateCode(@PathVariable String language) {
        try {
            if (!codeExecutionService.isLanguageSupported(language)) {
                return Result.error("不支持的编程语言: " + language);
            }
            
            String template = codeExecutionService.getTemplateCode(language);
            return Result.success(template, "获取模板代码成功");
            
        } catch (Exception e) {
            log.error("获取模板代码异常", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }
    
    /**
     * 安全检查
     */
    @PostMapping("/security-check")
    public Result<Map<String, Object>> securityCheck(@RequestBody Map<String, String> request) {
        try {
            String language = request.get("language");
            String code = request.get("code");
            
            if (language == null || code == null) {
                return Result.error("语言和代码不能为空");
            }
            
            boolean isSecure = securityValidator.validateCode(language, code);
            List<String> suggestions = securityValidator.getSecuritySuggestions(language, code);
            
            Map<String, Object> result = new HashMap<>();
            result.put("secure", isSecure);
            result.put("suggestions", suggestions);
            result.put("message", isSecure ? "代码安全检查通过" : "代码包含不安全内容");
            
            return Result.success(result, "安全检查完成");
            
        } catch (Exception e) {
            log.error("安全检查异常", e);
            return Result.error("检查异常: " + e.getMessage());
        }
    }
    
    /**
     * 获取执行环境信息
     */
    @GetMapping("/environment")
    public Result<Map<String, Object>> getEnvironmentInfo() {
        try {
            Map<String, Object> envInfo = new HashMap<>();
            
            // 系统信息
            envInfo.put("javaVersion", System.getProperty("java.version"));
            envInfo.put("osName", System.getProperty("os.name"));
            envInfo.put("osVersion", System.getProperty("os.version"));
            envInfo.put("architecture", System.getProperty("os.arch"));
            
            // 运行时信息
            Runtime runtime = Runtime.getRuntime();
            envInfo.put("availableProcessors", runtime.availableProcessors());
            envInfo.put("maxMemory", runtime.maxMemory() / 1024 / 1024 + " MB");
            envInfo.put("totalMemory", runtime.totalMemory() / 1024 / 1024 + " MB");
            envInfo.put("freeMemory", runtime.freeMemory() / 1024 / 1024 + " MB");
            
            // 支持的语言
            envInfo.put("supportedLanguages", codeExecutionService.getSupportedLanguages());
            
            // 限制信息
            Map<String, Object> limits = new HashMap<>();
            limits.put("maxCodeLength", 50000);
            limits.put("maxExecutionTime", 30);
            limits.put("maxMemoryUsage", 256);
            limits.put("maxOutputLength", 10000);
            envInfo.put("limits", limits);
            
            return Result.success(envInfo, "获取环境信息成功");
            
        } catch (Exception e) {
            log.error("获取环境信息异常", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试执行环境
     */
    @PostMapping("/test-environment")
    public Result<Map<String, Object>> testEnvironment(@RequestBody Map<String, String> request) {
        try {
            String language = request.getOrDefault("language", "python");
            
            if (!codeExecutionService.isLanguageSupported(language)) {
                return Result.error("不支持的编程语言: " + language);
            }
            
            // 使用模板代码测试
            String templateCode = codeExecutionService.getTemplateCode(language);
            
            CodeExecutionRequest testRequest = new CodeExecutionRequest();
            testRequest.setLanguage(language);
            testRequest.setCode(templateCode);
            testRequest.setTimeoutSeconds(5);
            testRequest.setMemoryLimitMB(64);
            
            CodeExecutionResult result = codeExecutionService.executeCode(testRequest);
            
            Map<String, Object> testResult = new HashMap<>();
            testResult.put("language", language);
            testResult.put("success", result.getSuccess());
            testResult.put("output", result.getOutput());
            testResult.put("executionTime", result.getExecutionTime());
            testResult.put("status", result.getStatusMessage());
            
            return Result.success(testResult, "环境测试完成");
            
        } catch (Exception e) {
            log.error("环境测试异常", e);
            return Result.error("测试失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取语言显示名称
     */
    private String getLanguageDisplayName(String language) {
        switch (language.toLowerCase()) {
            case "python": return "Python";
            case "java": return "Java";
            case "cpp": return "C++";
            case "c": return "C";
            case "javascript": return "JavaScript";
            case "go": return "Go";
            case "rust": return "Rust";
            default: return language;
        }
    }
    
    /**
     * 获取语言文件扩展名
     */
    private String getLanguageExtension(String language) {
        switch (language.toLowerCase()) {
            case "python": return ".py";
            case "java": return ".java";
            case "cpp": return ".cpp";
            case "c": return ".c";
            case "javascript": return ".js";
            case "go": return ".go";
            case "rust": return ".rs";
            default: return ".txt";
        }
    }
    
    /**
     * 从请求中获取用户ID
     */
    private Long getUserIdFromRequest(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            return jwtUtil.getUserIdFromToken(token);
        }
        return null;
    }
    
    /**
     * 获取客户端IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }
        
        return request.getRemoteAddr();
    }
}